Prolog Rules & Recursion (Lecture 3)
- في المحاضرة دي هنكمل على اللي بدأناه في الـ Prolog وهنركز أكتر على إزاي بنبني الـ (Rules).
- هنعرف إزاي الـ Prolog بيجاوب على الأسئلة بتاعتنا.
- هنعرف أنواع البيانات (Data Objects) اللي موجودة في اللغة.
- ,واهم حاجة، الـ Recursion (التكرار) في الـ Prolog وازاي بنستخدمه لبناء.
1. ازاي نعمل علاقات باستخدام القواعد (Defining Relations by Rules)
زي ما عرفنا قبل كده، الـ Rule بتستخدم عشان نستنتج حاجة بناءً على شروط معينة.
- الـ Fact: بتقول إن في حاجة دايماً صح (Unconditionally true). مثال:
male(aly). - الـ Rule: بتقول إن في حاجة صح بس بشرط (Depending on a condition).
مكونات الـ Rule ا (Clause Structure):
- أي Rule في الـ Prolog بتتكون من جزئين:
- الـ Head (الاستنتاج / Conclusion): ده اللي بيبقى على الشمال (Left-hand side).
- الـ Body (الشرط / Condition): ده اللي بيبقى على اليمين (Right-hand side) بعد علامة
:-اللي بتمثل كلمة (If).
مثال:
parent(X,Y) :- mother(X,Y).
- المعنى: "الشخص X يعتبر Parent للشخص Y لو كان X هو الـ Mother بتاعت Y".
- الـ
parent(X,Y)هي الـ Head. - الـ
mother(X,Y)هي الـ Body.
- الـ Predicate: هو الاسم اللي قبل الأقواس (زي
parentأوmother). - الـ Clause: هو السطر الواحد سواء كان Fact أو Rule. كل الـ Facts والـ Rules اللي ليها نفس الاسم بتشكل مع بعض تعريف الـ Predicate ده.
2. إزاي Prolog بيجاوب على الأسئلة؟ (How Prolog Answers Questions)
-
لما بتسأل الـ Prolog سؤال (Question/Goal)، بيعمل الآتي:
-
الـ Matching (المطابقة): بيدور في الـ Database من فوق لتحت (Top to Bottom) على أول Clause (سواء Fact أو Rule) الـ Head بتاعها بيطابق السؤال.
-
الـ Binding (ربط المتغيرات): لو لقى تطابق، بيدي الـ Variables اللي في السؤال القيمة اللي لقاها.
-
تنفيذ الـ Body (لو Rule): لو لقى تطابق مع Rule، بيستبدل السؤال الأساسي بالشروط اللي جوة الـ Body ويحاول يحققها (يثبت إنها صح) من الشمال لليمين كأنها أهداف جديدة .
-
الـ Backtracking (الرجوع لورا ): لو الـ Prolog فشل في تحقيق شرط معين، بيرجع للخطوة اللي قبلها (Backtrack) ويفك الارتباط (Unbind) ويحاول يشوف مسار تاني أو إجابة تانية (مثلاً يدور على Fact أو Rule تانية تنفع من مكان ما وقف).
-
3. أنواع البيانات في الـ Prolog (Data Objects / Terms)
الـ Data Objects (بيسموها كمان Terms) في Prolog بتنقسم لنوعين رئيسيين:
-
الـ Simple Objects :
-
الـ Constants (الثوابت):
- الـ Atoms (رموز/كلمات): زي
a,bob,x8r_2day(بتبدأ بحرف صغير Small letter). - الـ Strings (نصوص): زي
'a','Bob'(بتتحط بين علامات تنصيص). - الـ Integers (أرقام صحيحة): زي
987,-6.
- الـ Atoms (رموز/كلمات): زي
-
الـ Variables (المتغيرات):
- بتبدأ بحرف Capital زي
XأوA_var، أو بتبدأ بـ Underscore زي_Var. - الـ
_لوحدها دي معناها Anonymous Variable (متغير مجهول) بنستخدمه لو مش مهتمين بالقيمة اللي هترجع ومش عايزين نحفظها في مكان.
- بتبدأ بحرف Capital زي
-
-
الـ Structured Objects :
- الـ Structures.
- الـ Lists.
4. الـ Recursive Rules
الـ Recursion (التكرار) معناه إن الـ Rule بتستدعي نفسها جوة الـ Body بتاعها عشان تحل مشكلة معقدة أو سلسلة من العلاقات.
الفكرة الأساسية إن أي Recursive Relation لازم تتكون من جزئين (Two Rules) عشان ميفضلش يكرر نفسه للمالانهاية:
- الـ Direct Relation (الحالة المباشرة / Base Case): ودي اللي بتوقف التكرار.
- الـ Indirect Relation (الحالة الغير مباشرة / Recursive Step): ودي اللي بتستدعي نفسها وتكرر العملية عشان تكمل بحث في السلسلة (Chain).
مثال 1: علاقة الـ above
- لو عندنا Blocks محطوطة فوق بعض:
on(a, b).وon(b, c).
graph BT D["d"] C["c"] B["b"] A["a"] D --> C C --> B B --> A
- عايزين نعمل علاقة
above(X,Y)اللي بتقول إن X فوق Y حتى لو مش فوقها مباشرة.
% 1. Direct Relation (Base Case)
above(X, Y) :- on(X, Y).
% 2. Indirect Relation (Recursive Step)
above(X, Y) :- on(X, Z), above(Z, Y).
- المعنى: "الـ Block ا X فوق Y لو كان X موجود فوق Y مباشرة (on)، أو لو كان X فوق بلوك تاني اسمه Z، والـ Z دي فوق Y".
مثال 2: علاقة الـ predecessor (السلف / الجد الأكبر)
نفس الفكرة لو عندنا سلسلة من الآباء (Family Tree)، وعايزين نعرف لو شخص هو سلف (Predecessor) لشخص تاني يعني هل هو أبوه أو جده أو جد جده وهكذا:
% 1. Direct Predecessor
predecessor(X, Z) :- parent(X, Z).
% 2. Indirect Predecessor
predecessor(X, Z) :- parent(X, Y), predecessor(Y, Z).
مثال 3: علاقة الـ Route (المسار والمسافات)
نفس الفكرة بتطبق لحساب المسار بين مدينتين والمسافة بينهم باستخدام الجمع:
route(X, Y, D) :- link(X, Y, D).
route(X, Y, D) :- link(X, Z, D1), route(Z, Y, D2), D is D1 + D2.
توضيح لعملية الـ Recursion والـ Backtracking بالرسم
تعالى نشوف إزاي Prolog بيفكر خطوة بخطوة لو سألناه ?- predecessor(tom, pat). (عايزين نعرف هل tom هو جد pat؟)
graph TD
Goal["الهدف الأساسي:
?- predecessor(tom, pat)."]
Goal --> Rule1["يختبر القاعدة الأولى (المباشرة):
parent(tom, pat)."]
Rule1 -- "فشلت (Fails)" --> Rule2["يختبر القاعدة التانية (الغير مباشرة):
parent(tom, Y), predecessor(Y, pat)."]
Rule2 --> FindY["يحاول يطابق الجزء الأول:
parent(tom, Y)
عشان يجيب Y
نفترض لقى
parent(tom, bob) -> إذن Y = bob"]
FindY --> NewGoal["الـ Prolog يستدعي نفسه بالهدف الجديد:
?- predecessor(bob, pat)."]
NewGoal --> Rule1_2["يختبر القاعدة الأولى للهدف الجديد:
parent(bob, pat)."]
Rule1_2 -- "نجحت (Succeeds)" --> Done["تم إثبات المسار بنجاح!
النتيجة: Yes"]التتبع (Tracing) بتاع الـ Recursion بيعتمد إن الـ Prolog بيفضل يكسر الهدف الكبير لأهداف أصغر (Goals)، ولما يوصل لـ Fact بتنجح، بيرجع يبلغ النجاح ده للـ Rules اللي نادت عليها بشكل عكسي لحد ما يوصل للسؤال الأصلي ويقولك Yes.